package com.ytktt.study.week11.task10;

import io.lettuce.core.RedisClient;
import io.lettuce.core.ScoredValue;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 分数排名或者排行榜
 *
 * @author ytk
 */
@Slf4j
public class RankApplication {

    private static final Random RANDOM = new Random();

    private static final String MEMBER_PREFIX = "item-";

    public static void main(String[] args) throws InterruptedException {
        RedisClient redisClient = RedisClient.create("redis://localhost:6379/0");
        String key = "item";
        // 初始化数据
        initData(key, 100, redisClient);

        ExecutorService executorService = Executors.newFixedThreadPool(2);
        CountDownLatch countDownLatch = new CountDownLatch(2);
        executorService.submit(() -> {
            for (int i = 0; i < 40; i++) {
                randomAddData(key, 100, redisClient);
                try {
                    Thread.sleep(400L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            countDownLatch.countDown();
        });

        executorService.submit(() -> {
            for (int i = 0; i < 30; i++) {
                showTop(key, 10, redisClient);
                try {
                    Thread.sleep(600L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            countDownLatch.countDown();
        });

        countDownLatch.await();
        executorService.shutdown();
        redisClient.shutdown();
    }

    private static void initData(String key, int dataCount, RedisClient redisClient) {
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        RedisCommands<String, String> syncCommands = connection.sync();
        for (int i = 0; i < dataCount; i++) {
            syncCommands.zadd(key, 1.0, MEMBER_PREFIX + i);
        }
        connection.close();
    }

    private static void randomAddData(String key, int dataCount, RedisClient redisClient) {
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        RedisCommands<String, String> syncCommands = connection.sync();
        for (int i = 0; i < dataCount; i++) {
            syncCommands.zincrby(key,  RANDOM.nextDouble() * 100.0, MEMBER_PREFIX + i);
        }
        connection.close();
    }

    private static void showTop(String key, int top, RedisClient redisClient) {
        long timestamp = System.currentTimeMillis();
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        RedisCommands<String, String> syncCommands = connection.sync();
        List<ScoredValue<String>> rank = syncCommands.zrevrangeWithScores(key, 0, top - 1);
        for (ScoredValue<String> stringScoredValue : rank) {
            log.info("current timestamp: {} info: {}", timestamp, stringScoredValue);
        }
        log.info("===================================================================");
        connection.close();
    }
}
